﻿using System;
using System.Collections.Generic;
using System.Linq;
using LiSAClient.LiSAService;
using LiSAClient.ServiceProvider;

namespace LiSAClient.Core.Services
{
    public class ProjectService : BaseService
    {
        /// <summary>
        /// Retreives shortinfos for all projects for a user with the given ID
        /// </summary>
        /// <param name="userID">ID of the user to fetch projects for</param>
        /// <returns>The lsit of infos. If no user found, a new list</returns>
        public List<ProjectShortInfo> GetProjectShortinfos(Guid userID)
        {
            var projects = new List<ProjectShortInfo>();

            ServiceHandler.Instance.WithService(
                svc =>
                {
                    var userinfoquery = new ProjectShortinfoQuery
                    {
                        OwnerID = userID
                    };
                    var result = (ProjectShortinfoQueryResult)svc.ExecuteQuery(userinfoquery);
                    if (result != null && result.ShortInfos != null)
                    {
                        projects = result.ShortInfos;
                    }
                });
            return projects;
        }

        /// <summary>
        /// Adds a bibtex string to the project
        /// </summary>
        /// <param name="bibtexString">The bibtex string to parse srverside</param>
        /// <param name="projectID">The project to add the articles to</param>
        public void AddBibtexToProject(string bibtexString, Guid projectID)
        {
            ServiceHandler.Instance.WithService(
                svc =>
                {
                    var addBibTexCommand = new AddBibTexCommand
                    {
                        BibTexString = bibtexString,
                        ProjectID = projectID
                    };
                    svc.ExecuteCommand(addBibTexCommand);
                });
        }

        /// <summary>
        /// Retreives a project
        /// </summary>
        /// <param name="projectID">ID of the project to retreive</param>
        /// <returns>The corresponding Project to the ID</returns>
        public Project GetProjectByID(Guid projectID)
        {
            var returnProj = new Project { Title = "No project found for the given ID" };

            ServiceHandler.Instance.WithService(
            svc =>
            {
                var projectQuery = new GetProjectByIDQuery
                    {
                        ProjectID = projectID
                    };
                var result = (GetProjectByIDQueryResult)svc.ExecuteQuery(projectQuery);
                if (result != null && result.Project != null)
                {
                    returnProj = result.Project;
                }
            });
            return returnProj;
        }

        /// <summary>
        /// Creates a new project
        /// </summary>
        /// <param name="project">The ProjectDTO to create a Project from</param>
        public void CreateNewProject(Project project)
        {
            project.ProjectLead = AppContext.CurrentContext.User.ID;
            if (project.Users.All(x => x.ID != AppContext.CurrentContext.User.ID))
            {
                project.Users.Add(AppContext.CurrentContext.User);
            }
            ServiceHandler.Instance.WithService(
                 svc =>
                 {
                     var createProjCommand = new CreateProjectCommand
                     {
                         Project = project
                     };
                     svc.ExecuteCommand(createProjCommand);
                 });
        }

        /// <summary>
        /// Retreives articleFeedback for a given project
        /// </summary>
        /// <param name="projectID">ID of the Project</param>
        /// <returns>A List of all the ArticleFeeback pertinent to the query</returns>
        public List<ArticleFeedback> GetArticleFeedback(Guid projectID)
        {
            var feedBacks = new List<ArticleFeedback>();

            ServiceHandler.Instance.WithService(
                svc =>
                {
                    var userinfoquery = new ArticleFeedbackForProjectQuery
                    {
                        ProjectID = projectID
                    };
                    var result = (ArticleFeedbackForProjectQueryResult)svc.ExecuteQuery(userinfoquery);
                    if (result != null && result.FeedbackForProject != null)
                    {
                        feedBacks = result.FeedbackForProject;
                    }
                });
            return feedBacks;
        }

        /// <summary>
        /// Retreives articleFeedback for a given project and user
        /// </summary>
        /// <param name="projectID">ID of the Project</param>
        /// <param name="userID">ID of the User</param>
        /// <returns>A List of all the ArticleFeeback pertinent to the query</returns>
        public List<ArticleFeedback> GetArticleFeedback(Guid projectID, Guid userID)
        {
            var feedBacks = new List<ArticleFeedback>();

            ServiceHandler.Instance.WithService(
                svc =>
                {
                    var userinfoquery = new ProjectStagesQuery
                    {
                        ProjectID = projectID,
                        UserID = userID
                    };
                    var result = (ProjectStagesQueryResult)svc.ExecuteQuery(userinfoquery);
                    if (result != null && result.FeedBacks != null)
                    {
                        feedBacks = result.FeedBacks;
                    }
                });
            return feedBacks;
        }

        /// <summary>
        /// Retreives articles as a BibTex representation for a project
        /// </summary>
        /// <param name="projectID">ID of the Project</param>
        /// <returns>All the articles as a BibTex representation in a string</returns>
        public string GetArticlesAsBibtex(Guid projectID)
        {
            var result = string.Empty;

            ServiceHandler.Instance.WithService(
                svc =>
                {
                    var query = new GenerateBibtexQuery
                    {
                        ProjectID = projectID,
                    };
                    var queryResult = (GenerateBibtexQueryResult)svc.ExecuteQuery(query);
                    if (queryResult != null)
                    {
                        result = queryResult.BibtexFileContents;
                    }
                });
            return result;
        }

        /// <summary>
        /// Saves or Updates an ArticleFeedback
        /// </summary>
        /// <param name="theFeedback">the ArticleFeedback to be saved or updated</param>
        public void SaveOrUpdateArticleFeedback(ArticleFeedback theFeedback)
        {
            if (theFeedback == null) return;
            ServiceHandler.Instance.WithService(
                 svc =>
                 {
                     var createProjCommand = new SaveOrUpdateArticleFeedbackCommand
                     {
                         ArticleFeedbacks = new List<ArticleFeedback> { theFeedback }
                     };
                     svc.ExecuteCommand(createProjCommand);
                 });
        }


        /// <summary>
        /// Updates and Article
        /// </summary>
        /// <param name="article">The Article to be updated</param>
        public void UpdateArticle(Article article)
        {
            if (article == null) return;
            ServiceHandler.Instance.WithService(
                 svc =>
                 {
                     var updateArticleCmd = new UpdateArticleCommand()
                     {
                         Article = article
                     };
                     svc.ExecuteCommand(updateArticleCmd);
                 });
        }

        /// <summary>
        /// Have the server iterate through articles on a projhect and remove those with a majority vote saying they're OUT
        /// </summary>
        /// <param name="projectID">ID of the project to work on</param>
        public void RemoveBadArticles(Guid projectID)
        {
            if (projectID == Guid.Empty) return;
            ServiceHandler.Instance.WithService(
                 svc =>
                 {
                     var handleExcludedArticlesCmd = new HandleExcludedArticlesCommand
                     {
                         ProjectID = projectID
                     };
                     svc.ExecuteCommand(handleExcludedArticlesCmd);
                 });
        }

        /// <summary>
        /// Updates a project
        /// </summary>
        /// <param name="project">The Project DTO</param>
        public void UpdateProject(Project project)
        {
            ServiceHandler.Instance.WithService(
                 svc =>
                 {
                     var updateProjCommand = new UpdateProjectCommand
                     {
                         Project = project
                     };
                     svc.ExecuteCommand(updateProjCommand);
                 });
        }
    }
}
